package com.bc.trade.channel.ntlmh;

import java.text.DecimalFormat;
import java.util.Map;
import java.util.TreeMap;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.StatusLine;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import com.bc.common.CommonEnum.OrderStatus;
import com.bc.common.CommonEnum.Resp;
import com.bc.common.PayType;
import com.bc.common.message.DFReq;
import com.bc.common.message.DFResp;
import com.bc.trade.channel.IChannel;
import com.bc.trade.config.SystemConfig;
import com.bc.trade.message.QueryCardInfoReq;
import com.bc.trade.message.QueryCardInfoResp;
import com.bc.trade.message.QueryOrderResp;
import com.bc.trade.message.QuickPayReq;
import com.bc.trade.message.QuickPayResp;
import com.bc.trade.message.QuickPaySetReq;
import com.bc.trade.message.QuickPaySetResp;
import com.bc.trade.message.RefundReq;
import com.bc.trade.message.RefundResp;
import com.bc.trade.message.SendSMSReq;
import com.bc.trade.message.SendSMSResp;
import com.bc.trade.message.UnionPayReq;
import com.bc.trade.message.UnionPayResp;
import com.bc.trade.model.TradeOrder;
import com.fs.common.util.FSDate;
import com.fs.common.util.FSHttp;
import com.fs.common.util.FSJson;
import com.fs.common.util.FSString;

public class NtlmhChannel implements IChannel {

	private final String merchantId = SystemConfig.channelConfig.get("NTLMH_merchId");
	private final String secret = SystemConfig.channelConfig.get("NTLMH_key");
	
	private final String rootUrl = SystemConfig.channelConfig.get("NTLMH_rootUrl");
	private final String notifyUrl = SystemConfig.channelConfig.get("NTLMH_notifyUrl");
	private final String payUrl = SystemConfig.channelConfig.get("NTLMH_payUrl");
	private final String defrayReqUrl = SystemConfig.channelConfig.get("NTLMH_defrayReqUrl");
	private final String defrayQueryUrl = SystemConfig.channelConfig.get("NTLMH_defrayQueryUrl");
	
	@Override
	public QueryOrderResp query(TradeOrder order) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryOrderResp dfQuery(TradeOrder order) throws Exception {
		QueryOrderResp rsp = new QueryOrderResp();
		// 仅表示查询成功
		rsp.setCodeAndMsg(Resp.Success.getCode(), Resp.Success.getMsg());
		TreeMap<String, String> params = new TreeMap<String, String>();
		params.put("merNo", merchantId);
		params.put("orderNo", order.getOrderNo());
		params.put("sign", NtlmhUtil.signForDefray(params, secret));

		String reqFormData = FSString.convertMapToUrlParameter(params);
		System.out.println("汇卡请求付宝发送报文：-->[" + reqFormData + "]");
		
		String rspJson = FSHttp.postFormString(defrayQueryUrl, reqFormData, "UTF-8");
		System.out.println("汇卡接收付宝响应报文：<--[" + rspJson + "]");
		
		Map<String, String> resultMap = FSJson.toMap(rspJson);
		if ("SUCCESSED".equals(resultMap.get("status"))) {
			if (!OrderStatus.Success.getValue().equals(order.getOrderStatus())) {
				order.setOrderStatus(OrderStatus.Success.getValue());
				order.setRespCode(Resp.Success.getCode());
				order.setRespMsg(Resp.Success.getMsg());
				order.setPayTime(FSDate.getDateTime());
				order.setChannelOrderNo(resultMap.get("platNo"));
				order.update();
			}
			rsp.setPayTime(order.getPayTime());
			rsp.setOriginalRespCode(Resp.Success.getCode());
			rsp.setOriginalRespMsg(Resp.Success.getMsg());
		} else if ("PROCESSING".equals(resultMap.get("status"))) {
			if (!OrderStatus.Success.getValue().equals(order.getOrderStatus())) {
				order.setOrderStatus(OrderStatus.InProcess.getValue());
				order.setRespCode(Resp.InProcess.getCode());
				order.setRespMsg("CH"+resultMap.get("desc"));
				order.setPayTime(FSDate.getDateTime());
				order.setChannelOrderNo(resultMap.get("platNo"));
				order.update();
			}
			rsp.setOriginalRespCode(Resp.InProcess.getCode());
			rsp.setOriginalRespMsg("CH"+resultMap.get("desc"));
		} else if ("FAILED".equals(resultMap.get("status"))) {
			if (!OrderStatus.Success.getValue().equals(order.getOrderStatus())) {
				order.setOrderStatus(OrderStatus.Fail.getValue());
				order.setRespCode(Resp.Fail.getCode());
				order.setRespMsg(resultMap.get("desc"));
				order.setPayTime(FSDate.getDateTime());
				order.setChannelOrderNo(resultMap.get("platNo"));
				order.update();
			}
			rsp.setOriginalRespCode(Resp.Fail.getCode());
			rsp.setOriginalRespMsg("CH"+resultMap.get("desc"));
		} else {
			rsp.setCodeAndMsg(Resp.Fail.getCode(), "渠道响应异常");
		}
		return rsp;
	}

	@Override
	public DFResp df(DFReq req, TradeOrder order) throws Exception {
		DFResp rsp = new DFResp(req);
		
		if (order.getAmount() % 100 != 0) {
			order.setOrderStatus(OrderStatus.Fail.getValue());
			order.setRespCode(Resp.Fail.getCode());
			order.setRespMsg("通道限制金额必须为元的整数");
			order.update();
			rsp.setRespCode(Resp.Fail.getCode());
			rsp.setRespMsg(order.getRespMsg());
			return rsp;
		}
		
		//DecimalFormat df = new DecimalFormat("0.00");
		TreeMap<String, String> params = new TreeMap<String, String>();
		params.put("merNo", merchantId);
		params.put("orderNo", order.getOrderNo());
		params.put("orderAmt", Integer.toString(order.getAmount()/100));	// 这个渠道只能接受整数金额
		params.put("userName", order.getCustomerName());
		params.put("cardNo", order.getBankCardNo());
		params.put("bankName", req.getBankName());
		params.put("bankProvince", "");
		params.put("bankCity", "");
		params.put("bankFullName", "");
		params.put("sign", NtlmhUtil.signForDefray(params, secret));
		
		String reqFormData = FSString.convertMapToUrlParameter(params);
		System.out.println("汇卡请求付宝发送报文：-->[" + reqFormData + "]");
		
		String rspJson = FSHttp.postFormString(defrayReqUrl, reqFormData, "UTF-8");
		System.out.println("汇卡接收付宝响应报文：<--[" + rspJson + "]");
		Map<String, String> resultMap = FSJson.toMap(rspJson);
		if ("0000".equals(resultMap.get("code"))) {
			order.setOrderStatus(OrderStatus.Success.getValue());
			order.setRespCode(Resp.Success.getCode());
			order.setRespMsg(Resp.Success.getMsg());
			order.setPayTime(FSDate.getDateTime());
			order.setChannelOrderNo(resultMap.get("platNo"));
			order.update();
			rsp.setRespCode(Resp.Success.getCode());
			rsp.setRespMsg(order.getRespMsg());
		} else if ("0001".equals(resultMap.get("code"))) {
			order.setOrderStatus(OrderStatus.InProcess.getValue());
			order.setRespCode(Resp.InProcess.getCode());
			order.setRespMsg(resultMap.get("desc"));
			order.setPayTime(FSDate.getDateTime());
			order.setChannelOrderNo(resultMap.get("platNo"));
			order.update();
			rsp.setRespCode(Resp.InProcess.getCode());
			rsp.setRespMsg("CH" + order.getRespMsg());
		} else {
			order.setOrderStatus(OrderStatus.Fail.getValue());
			order.setRespCode(Resp.Fail.getCode());
			order.setRespMsg(resultMap.get("desc"));
			order.setPayTime(FSDate.getDateTime());
			order.setChannelOrderNo(resultMap.get("platNo"));
			order.update();
			rsp.setRespCode(Resp.Fail.getCode());
			rsp.setRespMsg("CH" + order.getRespMsg());
		}
		return rsp;
	}

	@Override
	public UnionPayResp unionpay(UnionPayReq req, TradeOrder order) throws Exception {
		UnionPayResp rsp = new UnionPayResp(req);
		DecimalFormat df = new DecimalFormat("0.00");
		
		// HTTP请求客户端
		CloseableHttpClient httpclient = HttpClients.createDefault();
		RequestConfig.Builder builder = RequestConfig.custom()
				.setConnectionRequestTimeout(30000)
				.setSocketTimeout(90000);
		
		// 请求参数
		TreeMap<String, String> map = new TreeMap<>();
		map.put("partner", merchantId);
		if (PayType.UNION_PAY.equals(req.getPayType())) {
			map.put("banktype", "wypay");					// 网银非直联
			builder.setRedirectsEnabled(false);			// 禁止重定向，以便取得收银台地址
		} else if (PayType.UNION_PAY_SUB.equals(req.getPayType())) {
			map.put("banktype", "QUICKPAY");			//快捷支付(网关形式)
		}
		map.put("paymoney", df.format(order.getAmount()/100.0));
		map.put("ordernumber", order.getOrderNo());
		map.put("callbackurl", notifyUrl); // 下行异步通知地址
		map.put("hrefbackurl", order.getReturnUrl()); // 下行同步通知地址
		map.put("attach", order.getRemark()); // 备注
		map.put("sign", NtlmhUtil.signMD5(map, secret));// 签名处理
		
		// 获取get参数字符串
		StringBuilder data = new StringBuilder();
		for (Map.Entry<String, String> entry : map.entrySet()) {
			data.append(entry.getKey()).append('=').append(entry.getValue()).append('&');
		}
		data.deleteCharAt(data.length() - 1);
		String reqText = data.toString();
		System.out.println("请求付宝发送报文：-->[" + reqText + "]");
		RequestConfig config = builder.build();
		HttpGet httpGet = new HttpGet(payUrl+'?'+reqText);
		httpGet.setConfig(config);
		httpGet.setHeader("content-type", "text/xml; charset=UTF-8");
		httpGet.setHeader("Accept-Charset", "UTF-8");
		CloseableHttpResponse httpRsp = httpclient.execute(httpGet);
		// 正常的响应内容为一个HTML网页表单并会自动提交，只要能正常响应网页则认为下单成功
		StatusLine sl = httpRsp.getStatusLine();
		try {
		    HttpEntity httpEntity = httpRsp.getEntity();
		    String rspText = EntityUtils.toString(httpEntity, "UTF-8");
		    EntityUtils.consume(httpEntity);
		    if (sl.getStatusCode() == 200 || sl.getStatusCode() == 302) {
				if (PayType.UNION_PAY.equals(req.getPayType())) {
					rsp.setType("1");
				    rsp.setHtml(rspText);
					Header header = httpRsp.getFirstHeader("Location");
					if(header != null) {
						String url = header.getValue();
						rsp.setUrl(rootUrl + url);
					}
				}else {
					rsp.setType("0");
				    rsp.setHtml(rspText);
				}
				// 返回网页状态200则下单成功
				order.setRespCode(Resp.InProcess.getCode());
				order.setRespMsg(Resp.InProcess.getMsg());
				rsp.setCodeAndMsg(Resp.Success.getCode(), Resp.Success.getMsg());
		    }else {
				// 其他状态则认为下单失败
				order.setRespCode(Resp.Fail.getCode());
				order.setRespMsg(Resp.Fail.getMsg());
				order.setOrderStatus(OrderStatus.Fail.getValue());
				rsp.setCodeAndMsg(Resp.Fail.getCode(), "失败CH("+sl.getStatusCode()+")");
			}
			System.out.println("接收付宝响应报文：<--(" + sl.getStatusCode() + ") [" + rspText + "]");
		} finally {
			httpRsp.close();
		}
		order.update();
		return rsp;
	}

	@Override
	public QuickPaySetResp quickPaySet(QuickPaySetReq req, TradeOrder order) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QuickPayResp quickPay(QuickPayReq req, TradeOrder order) throws Exception {
		return null;
	}

	@Override
	public SendSMSResp sendSMS(SendSMSReq req) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public QueryCardInfoResp queryCardInfo(QueryCardInfoReq req) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public RefundResp refund(RefundReq req, TradeOrder refundOrder, TradeOrder orignOrder) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

}
